package sg.edu.nus.iss.billing.template;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import sg.edu.nus.iss.billing.entity.Bill;
import sg.edu.nus.iss.billing.localization.MessageKeyManager;
import sg.edu.nus.iss.billing.template.interfaces.ParseAction;


/**
 * 
 * A factory to generate a list of parse action based on Java bean.
 * It uses Java Reflection to analyse the bean and generate a list of
 * parseKey and parseValue based on the getter method name and getter method
 * return value
 * 
 * @author Daniel
 * 
 */
public class ReflectionParseActionsFactory {
	
	private static List<ParseAction> generateParseList(Object obj, Class clazz, ConvertStrategy strategy) {
		List<ParseAction> result = new ArrayList<ParseAction>();
		Method m[] = obj.getClass().getDeclaredMethods();
		for (int i=0; i < m.length; i++) {
			if (m[i].getName().startsWith("get") && (clazz == m[i].getReturnType())) {
				String parseKey = "\\$\\{" + m[i].getName() + "\\}";
				String parseValue = "";
				try {
					Object parseValueObj = m[i].invoke(obj);
					if (strategy != null)
						parseValue = strategy.convert(parseValueObj);
					else 
						parseValue = (String)parseValueObj;
				} catch (IllegalAccessException e) {
					parseValue = "parseError: " + e.getMessage();
				} catch (InvocationTargetException e) {
					parseValue = "parseError: " + e.getMessage();
				} catch (Exception e) {
					parseValue = "parseError: " + e.getMessage();
				}
				BasicParseAction action = new BasicParseAction(parseKey, parseValue);
				result.add(action);
			}
		}
		return result;
	}
	
	public static List<ParseAction> generateParseListForDateField(Object obj, DateFormat dateFormat) {
		ConvertStrategy strategy = new ConvertStrategy(dateFormat);
		List<ParseAction> result = generateParseList(obj, Date.class, strategy);
		return result;
	}
	
	public static List<ParseAction> generateParseListForBigDecimalField(Object obj, DecimalFormat decimalFormat) {
		ConvertStrategy strategy = new ConvertStrategy(decimalFormat);
		return generateParseList(obj, BigDecimal.class, strategy);
	}
	
	public static List<ParseAction> generateParseListForStringField(Object obj) {
		return generateParseList(obj, String.class, null);
	}
	
}
